PHP CompleteComplete Tips & Secrets for Professionals
TipsPHP & Secrets for Professionals
300+ pages of professional hints and tricks
Disclaimer This is an unocial free book created for educational purposes and is GoalKicker.com not aliated with ocial PHP group(s) or company(s). Free Programming Books All trademarks and registered trademarks are the property of their respective owners Contents
About ...... 1 Chapter 1: Getting started with PHP ...... 2 Section 1.1: HTML output from web server ...... 2 Section 1.2: Hello, World! ...... 3 Section 1.3: Non-HTML output from web server ...... 3 Section 1.4: PHP built-in server ...... 4 Section 1.5: PHP CLI ...... 5 Section 1.6: Instruction Separation ...... 6 Section 1.7: PHP Tags ...... 7 Chapter 2: Variables ...... 7 Section 2.1: Accessing A Variable Dynamically By Name (Variable variables) ...... 8 Section 2.2: Data Types ...... 9 Section 2.3: Global variable best practices ...... 11 Section 2.4: Default values of uninitialized variables ...... 13 Section 2.5: Variable Value Truthiness and Identical Operator ...... 13 Chapter 3: Arrays ...... 15 Section 3.1: Initializing an Array ...... 16 Section 3.2: Check if key exists ...... 18 Section 3.3: Validating the array type ...... 19 Section 3.4: Creating an array of variables ...... 19 Section 3.5: Checking if a value exists in array ...... 19 Section 3.6: ArrayAccess and Iterator Interfaces ...... 20 Chapter 4: Functional Programming ...... 23 Section 4.1: Closures ...... 23 Section 4.2: Assignment to variables ...... 24 Section 4.3: Objects as a function ...... 24 Section 4.4: Using outside variables ...... 25 Section 4.5: Anonymous function ...... 25 Section 4.6: Pure functions ...... 26 Section 4.7: Common functional methods in PHP ...... 26 Section 4.8: Using built-in functions as callbacks ...... 27 Section 4.9: Scope ...... 27 Section 4.10: Passing a callback function as a parameter ...... 27 Chapter 5: Types ...... 28 Section 5.1: Type Comparison ...... 28 Section 5.2: Boolean ...... 29 Section 5.3: Float ...... 30 Section 5.4: Strings ...... 30 Section 5.5: Callable ...... 32 Section 5.6: Resources ...... 32 Section 5.7: Type Casting ...... 33 Section 5.8: Type Juggling ...... 34 Section 5.9: Null ...... 34 Section 5.10: Integers ...... 34 Chapter 6: Autoloading Primer ...... 35 Section 6.1: Autoloading as part of a framework solution ...... 35 Section 6.2: Inline class definition, no loading required ...... 36 Section 6.3: Manual class loading with require ...... 36 Section 6.4: Autoloading replaces manual class definition loading ...... 37 Section 6.5: Autoloading with Composer ...... 37 Chapter 7: Exception Handling and Error Reporting ...... 38 Section 7.1: Setting error reporting and where to display them ...... 38 Section 7.2: Logging fatal errors ...... 38 Chapter 8: Working with Dates and Time ...... 39 Section 8.1: Getting the dierence between two dates / times ...... 39 Section 8.2: Convert a date into another format ...... 40 Section 8.3: Parse English date descriptions into a Date format ...... 41 Section 8.4: Using Predefined Constants for Date Format ...... 41 Chapter 9: Sending Email ...... 42 Section 9.1: Sending Email - The basics, more details, and a full example ...... 42 Section 9.2: Sending HTML Email Using mail() ...... 45 Section 9.3: Sending Email With An Attachment Using mail() ...... 45 Section 9.4: Sending Plain Text Email Using PHPMailer ...... 47 Section 9.5: Sending HTML Email Using PHPMailer ...... 48 Section 9.6: Sending Email With An Attachment Using PHPMailer ...... 48 Section 9.7: Sending Plain Text Email Using Sendgrid ...... 49 Section 9.8: Sending Email With An Attachment Using Sendgrid ...... 49 Chapter 10: Sessions ...... 50 Section 10.1: session_start() Options ...... 50 Section 10.2: Session Locking ...... 51 Section 10.3: Manipulating session data ...... 51 Section 10.4: Destroy an entire session ...... 52 Section 10.5: Safe Session Start With no Errors ...... 52 Section 10.6: Session name ...... 53 Chapter 11: Cookies ...... 53 Section 11.1: Modifying a Cookie ...... 54 Section 11.2: Setting a Cookie ...... 54 Section 11.3: Checking if a Cookie is Set ...... 55 Section 11.4: Removing a Cookie ...... 55 Section 11.5: Retrieving a Cookie ...... 55 Chapter 12: Classes and Objects ...... 55 Section 12.1: Class Constants ...... 56 Section 12.2: Abstract Classes ...... 58 Section 12.3: Late static binding ...... 60 Section 12.4: Namespacing and Autoloading ...... 61 Section 12.5: Method and Property Visibility ...... 62 Section 12.6: Interfaces ...... 64 Section 12.7: Final Keyword ...... 67 Section 12.8: Autoloading ...... 68 Section 12.9: Calling a parent constructor when instantiating a child ...... 69 Section 12.10: Dynamic Binding ...... 70 Section 12.11: $this, self and static plus the singleton ...... 71 Section 12.12: Defining a Basic Class ...... 73 Section 12.13: Anonymous Classes ...... 75 Chapter 13: Password Hashing Functions ...... 76 Section 13.1: Creating a password hash ...... 76 Section 13.2: Determine if an existing password hash can be upgraded to a stronger algorithm ...... 77 Section 13.3: Verifying a password against a hash ...... 78 Chapter 14: Output Buering ...... 79 Section 14.1: Basic usage getting content between buers and clearing ...... 79 Section 14.2: Processing the buer via a callback ...... 79 Section 14.3: Nested output buers ...... 80 Section 14.4: Running output buer before any content ...... 81 Section 14.5: Stream output to client ...... 81 Section 14.6: Using Output buer to store contents in a file, useful for reports, invoices etc ...... 82 Section 14.7: Typical usage and reasons for using ob_start ...... 82 Section 14.8: Capturing the output buer to re-use later ...... 82 Chapter 15: JSON ...... 83 Section 15.1: Decoding a JSON string ...... 84 Section 15.2: Encoding a JSON string ...... 86 Section 15.3: Debugging JSON errors ...... 89 Section 15.4: Using JsonSerializable in an Object ...... 90 Section 15.5: Header json and the returned response ...... 91 Chapter 16: SOAP Client ...... 92 Section 16.1: WSDL Mode ...... 92 Section 16.2: Non-WSDL Mode ...... 92 Section 16.3: Classmaps ...... 93 Section 16.4: Tracing SOAP request and response ...... 94 Chapter 17: Reflection ...... 94 Section 17.1: Feature detection of classes or objects ...... 94 Section 17.2: Testing private/protected methods ...... 95 Section 17.3: Accessing private and protected member variables ...... 96 Chapter 18: Using cURL in PHP ...... 98 Section 18.1: Basic Usage (GET Requests) ...... 98 Section 18.2: POST Requests ...... 99 Section 18.3: Using Cookies ...... 99 Section 18.4: Using multi_curl to make multiple POST requests ...... 100 Section 18.5: Sending multi-dimensional data and multiple files with CurlFile in one request ...... 101 Section 18.6: Creating and sending a request with a custom method ...... 104 Section 18.7: Get and Set custom http headers in php ...... 104 Chapter 19: Dependency Injection ...... 105 Section 19.1: Constructor Injection ...... 105 Section 19.2: Setter Injection ...... 106 Section 19.3: Container Injection ...... 107 Chapter 20: XML ...... 108 Section 20.1: Create a XML using DomDocument ...... 108 Section 20.2: Read a XML document with DOMDocument ...... 109 Section 20.3: Leveraging XML with PHP's SimpleXML Library ...... 110 Section 20.4: Create an XML file using XMLWriter ...... 112 Section 20.5: Read a XML document with SimpleXML ...... 113 Chapter 21: Regular Expressions (regexp/PCRE) ...... 114 Section 21.1: Global RegExp match ...... 114 Section 21.2: String matching with regular expressions ...... 115 Section 21.3: Split string into array by a regular expression ...... 116 Section 21.4: String replacing with regular expression ...... 116 Section 21.5: String replace with callback ...... 116 Chapter 22: Traits ...... 117 Section 22.1: What is a Trait? ...... 117 Section 22.2: Traits to facilitate horizontal code reuse ...... 118 Section 22.3: Conflict Resolution ...... 119 Section 22.4: Implementing a Singleton using Traits ...... 120 Section 22.5: Traits to keep classes clean ...... 121 Section 22.6: Multiple Traits Usage ...... 122 Section 22.7: Changing Method Visibility ...... 122 Chapter 23: Namespaces ...... 123 Section 23.1: Declaring namespaces ...... 123 Section 23.2: Referencing a class or function in a namespace ...... 124 Section 23.3: Declaring sub-namespaces ...... 125 Section 23.4: What are Namespaces? ...... 125 Chapter 24: Parsing HTML ...... 125 Section 24.1: Parsing HTML from a string ...... 125 Section 24.2: Using XPath ...... 126 Section 24.3: SimpleXML ...... 126 Chapter 25: Composer Dependency Manager ...... 127 Section 25.1: What is Composer? ...... 127 Section 25.2: Autoloading with Composer ...... 128 Section 25.3: Dierence between 'composer install' and 'composer update' ...... 129 Section 25.4: Composer Available Commands ...... 129 Section 25.5: Benefits of Using Composer ...... 130 Section 25.6: Installation ...... 131 Chapter 26: Magic Methods ...... 131 Section 26.1: __call() and __callStatic() ...... 131 Section 26.2: __get(), __set(), __isset() and __unset() ...... 132 Section 26.3: __construct() and __destruct() ...... 134 Section 26.4: __toString() ...... 134 Section 26.5: __clone() ...... 135 Section 26.6: __invoke() ...... 135 Section 26.7: __sleep() and __wakeup() ...... 136 Section 26.8: __debugInfo() ...... 137 Chapter 27: Alternative Syntax for Control Structures ...... 137 Section 27.1: Alternative if/else statement ...... 137 Section 27.2: Alternative for statement ...... 137 Section 27.3: Alternative while statement ...... 138 Section 27.4: Alternative foreach statement ...... 138 Section 27.5: Alternative switch statement ...... 138 Chapter 28: File handling ...... 139 Section 28.1: Convenience functions ...... 139 Section 28.2: Deleting files and directories ...... 140 Section 28.3: Getting file information ...... 141 Section 28.4: Stream-based file IO ...... 143 Section 28.5: Moving and Copying files and directories ...... 144 Section 28.6: Minimize memory usage when dealing with large files ...... 145 Chapter 29: Magic Constants ...... 146 Section 29.1: Dierence between __FUNCTION__ and __METHOD__ ...... 146 Section 29.2: Dierence between __CLASS__, get_class() and get_called_class() ...... 146 Section 29.3: File & Directory Constants ...... 147 Chapter 30: Type hinting ...... 148 Section 30.1: Type hinting classes and interfaces ...... 148 Section 30.2: Type hinting scalar types, arrays and callables ...... 149 Section 30.3: Nullable type hints ...... 150 Section 30.4: Type hinting generic objects ...... 151 Section 30.5: Type Hinting No Return(Void) ...... 152 Chapter 31: Multi Threading Extension ...... 152 Section 31.1: Getting Started ...... 152 Section 31.2: Using Pools and Workers ...... 153 Chapter 32: Filters & Filter Functions ...... 154 Section 32.1: Validating Boolean Values ...... 154 Section 32.2: Validating A Number Is A Float ...... 154 Section 32.3: Validate A MAC Address ...... 155 Section 32.4: Sanitze Email Addresses ...... 156 Section 32.5: Sanitize Integers ...... 156 Section 32.6: Sanitize URLs ...... 157 Section 32.7: Validate Email Address ...... 157 Section 32.8: Validating A Value Is An Integer ...... 157 Section 32.9: Validating An Integer Falls In A Range ...... 158 Section 32.10: Validate a URL ...... 158 Section 32.11: Sanitize Floats ...... 160 Section 32.12: Validate IP Addresses ...... 162 Section 32.13: Sanitize filters ...... 163 Chapter 33: Generators ...... 163 Section 33.1: The Yield Keyword ...... 163 Section 33.2: Reading a large file with a generator ...... 164 Section 33.3: Why use a generator? ...... 165 Section 33.4: Using the send()-function to pass values to a generator ...... 165 Chapter 34: Operators ...... 166 Section 34.1: Null Coalescing Operator (??) ...... 166 Section 34.2: Spaceship Operator (<=>) ...... 167 Section 34.3: Execution Operator (``) ...... 168 Section 34.4: Incrementing (++) and Decrementing Operators (--) ...... 168 Section 34.5: Ternary Operator (?:) ...... 168 Section 34.6: Logical Operators (&&/AND and ||/OR) ...... 169 Section 34.7: String Operators (. and .=) ...... 169 Section 34.8: Object and Class Operators ...... 169 Section 34.9: Combined Assignment (+= etc) ...... 171 Section 34.10: Altering operator precedence (with parentheses) ...... 172 Section 34.11: Basic Assignment (=) ...... 172 Section 34.12: Association ...... 172 Section 34.13: Comparison Operators ...... 173 Section 34.14: Bitwise Operators ...... 174 Section 34.15: instanceof (type operator) ...... 176 Chapter 35: Constants ...... 178 Section 35.1: Defining constants ...... 178 Section 35.2: Class Constants ...... 179 Section 35.3: Checking if constant is defined ...... 179 Section 35.4: Using constants ...... 180 Section 35.5: Constant arrays ...... 181 Chapter 36: UTF-8 ...... 181 Section 36.1: Input ...... 181 Section 36.2: Output ...... 182 Section 36.3: Data Storage and Access ...... 182 Chapter 37: URLs ...... 183 Section 37.1: Parsing a URL ...... 183 Section 37.2: Build an URL-encoded query string from an array ...... 184 Section 37.3: Redirecting to another URL ...... 184 Chapter 38: Object Serialization ...... 185 Section 38.1: Serialize / Unserialize ...... 185 Section 38.2: The Serializable interface ...... 185 Chapter 39: PHPDoc ...... 186 Section 39.1: Describing a variable ...... 186 Section 39.2: Adding metadata to functions ...... 187 Section 39.3: Describing parameters ...... 187 Section 39.4: Collections ...... 188 Section 39.5: Adding metadata to files ...... 190 Section 39.6: Inheriting metadata from parent structures ...... 190 Chapter 40: Contributing to the PHP Manual ...... 190 Section 40.1: Improve the ocial documentation ...... 190 Section 40.2: Tips for contributing to the manual ...... 191 Chapter 41: String Parsing ...... 191 Section 41.1: Splitting a string by separators ...... 191 Section 41.2: Substring ...... 192 Section 41.3: Searching a substring with strpos ...... 193 Section 41.4: Parsing string using regular expressions ...... 194 Chapter 42: Loops ...... 195 Section 42.1: continue ...... 195 Section 42.2: break ...... 196 Section 42.3: foreach ...... 197 Section 42.4: do...while ...... 198 Section 42.5: for ...... 198 Section 42.6: while ...... 199 Chapter 43: Control Structures ...... 199 Section 43.1: if else ...... 199 Section 43.2: Alternative syntax for control structures ...... 200 Section 43.3: while ...... 200 Section 43.4: do-while ...... 200 Section 43.5: goto ...... 200 Section 43.6: declare ...... 201 Section 43.7: include & require ...... 201 Section 43.8: return ...... 202 Section 43.9: for ...... 202 Section 43.10: foreach ...... 203 Section 43.11: if elseif else ...... 203 Section 43.12: if ...... 204 Section 43.13: switch ...... 204 Chapter 44: Serialization ...... 205 Section 44.1: Serialization of dierent types ...... 205 Section 44.2: Security Issues with unserialize ...... 206 Chapter 45: Closure ...... 208 Section 45.1: Basic usage of a closure ...... 208 Section 45.2: Using external variables ...... 209 Section 45.3: Basic closure binding ...... 209 Section 45.4: Closure binding and scope ...... 210 Section 45.5: Binding a closure for one call ...... 211 Section 45.6: Use closures to implement observer pattern ...... 212 Chapter 46: Reading Request Data ...... 213 Section 46.1: Reading raw POST data ...... 213 Section 46.2: Reading POST data ...... 214 Section 46.3: Reading GET data ...... 214 Section 46.4: Handling file upload errors ...... 214 Section 46.5: Passing arrays by POST ...... 215 Section 46.6: Uploading files with HTTP PUT ...... 216 Chapter 47: Type juggling and Non-Strict Comparison Issues ...... 217 Section 47.1: What is Type Juggling? ...... 217 Section 47.2: Reading from a file ...... 217 Section 47.3: Switch surprises ...... 218 Section 47.4: Strict typing ...... 219 Chapter 48: Security ...... 219 Section 48.1: PHP Version Leakage ...... 220 Section 48.2: Cross-Site Scripting (XSS) ...... 220 Section 48.3: Cross-Site Request Forgery ...... 221 Section 48.4: Command Line Injection ...... 223 Section 48.5: Stripping Tags ...... 224 Section 48.6: File Inclusion ...... 224 Section 48.7: Error Reporting ...... 225 Section 48.8: Uploading files ...... 226 Chapter 49: PHP MySQLi ...... 228 Section 49.1: Close connection ...... 228 Section 49.2: MySQLi connect ...... 228 Section 49.3: Loop through MySQLi results ...... 229 Section 49.4: Prepared statements in MySQLi ...... 229 Section 49.5: Escaping Strings ...... 230 Section 49.6: Debugging SQL in MySQLi ...... 230 Section 49.7: MySQLi query ...... 231 Section 49.8: How to get data from a prepared statement ...... 231 Section 49.9: MySQLi Insert ID ...... 233 Chapter 50: Command Line Interface (CLI) ...... 234 Section 50.1: Handling Program Options ...... 234 Section 50.2: Argument Handling ...... 235 Section 50.3: Input and Output Handling ...... 236 Section 50.4: Return Codes ...... 237 Section 50.5: Restrict script execution to command line ...... 238 Section 50.6: Behavioural dierences on the command line ...... 238 Section 50.7: Running your script ...... 238 Section 50.8: Edge Cases of getopt() ...... 239 Section 50.9: Running built-in web server ...... 240 Chapter 51: Localization ...... 240 Section 51.1: Localizing strings with gettext() ...... 240 Chapter 52: Debugging ...... 241 Section 52.1: Dumping variables ...... 241 Section 52.2: Displaying errors ...... 241 Section 52.3: phpinfo() ...... 242 Section 52.4: Xdebug ...... 242 Section 52.5: Error Reporting (use them both) ...... 243 Section 52.6: phpversion() ...... 243 Chapter 53: Superglobal Variables PHP ...... 244 Section 53.1: Suberglobals explained ...... 244 Section 53.2: PHP5 SuperGlobals ...... 251 Chapter 54: Unit Testing ...... 254 Section 54.1: Testing class rules ...... 254 Section 54.2: PHPUnit Data Providers ...... 257 Section 54.3: Test exceptions ...... 260 Chapter 55: Variable Scope ...... 261 Section 55.1: Superglobal variables ...... 261 Section 55.2: Static properties and variables ...... 262 Section 55.3: User-defined global variables ...... 262 Chapter 56: References ...... 263 Section 56.1: Assign by Reference ...... 263 Section 56.2: Return by Reference ...... 264 Section 56.3: Pass by Reference ...... 265 Chapter 57: Compilation of Errors and Warnings ...... 266 Section 57.1: Parse error: syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM ...... 266 Section 57.2: Notice: Undefined index ...... 266 Section 57.3: Warning: Cannot modify header information - headers already sent ...... 267 Chapter 58: Installing a PHP environment on Windows ...... 267 Section 58.1: Download, Install and use WAMP ...... 267 Section 58.2: Install PHP and use it with IIS ...... 268 Section 58.3: Download and Install XAMPP ...... 269 Chapter 59: Datetime Class ...... 270 Section 59.1: Create Immutable version of DateTime from Mutable prior PHP 5.6 ...... 270 Section 59.2: Add or Subtract Date Intervals ...... 270 Section 59.3: getTimestamp ...... 271 Section 59.4: setDate ...... 271 Section 59.5: Create DateTime from custom format ...... 271 Section 59.6: Printing DateTimes ...... 271 Chapter 60: Headers Manipulation ...... 272 Section 60.1: Basic Setting of a Header ...... 273 Chapter 61: Performance ...... 273 Section 61.1: Profiling with Xdebug ...... 273 Section 61.2: Memory Usage ...... 275 Section 61.3: Profiling with XHProf ...... 276 Chapter 62: Common Errors ...... 277 Section 62.1: Call fetch_assoc on boolean ...... 277 Section 62.2: Unexpected $end ...... 277 Chapter 63: Installing on Linux/Unix Environments ...... 277 Section 63.1: Command Line Install Using APT for PHP 7 ...... 278 Section 63.2: Installing in Enterprise Linux distributions (CentOS, Scientific Linux, etc) ...... 278 Chapter 64: Contributing to the PHP Core ...... 279 Section 64.1: Setting up a basic development environment ...... 279 Chapter 65: Coding Conventions ...... 279 Section 65.1: PHP Tags ...... 279 Chapter 66: Using MongoDB ...... 280 Section 66.1: Connect to MongoDB ...... 280 Section 66.2: Get multiple documents - find() ...... 280 Section 66.3: Get one document - findOne() ...... 280 Section 66.4: Insert document ...... 281 Section 66.5: Update a document ...... 281 Section 66.6: Delete a document ...... 281 Chapter 67: Asynchronous programming ...... 281 Section 67.1: Advantages of Generators ...... 281 Section 67.2: Using Icicle event loop ...... 282 Section 67.3: Spawning non-blocking processes with proc_open() ...... 282 Section 67.4: Reading serial port with Event and DIO ...... 284 Section 67.5: HTTP Client Based on Event Extension ...... 286 Section 67.6: HTTP Client Based on Ev Extension ...... 288 Section 67.7: Using Amp event loop ...... 292 Chapter 68: Using SQLSRV ...... 293 Section 68.1: Retrieving Error Messages ...... 293 Section 68.2: Fetching Query Results ...... 294 Section 68.3: Creating a Connection ...... 294 Section 68.4: Making a Simple Query ...... 295 Section 68.5: Invoking a Stored Procedure ...... 295 Section 68.6: Making a Parameterised Query ...... 295 Chapter 69: Unicode Support in PHP ...... 295 Section 69.1: Converting Unicode characters to “\uxxxx” format using PHP ...... 295 Section 69.2: Converting Unicode characters to their numeric value and/or HTML entities using PHP ...... 296 Section 69.3: Intl extention for Unicode support ...... 298 Chapter 70: Functions ...... 298 Section 70.1: Variable-length argument lists ...... 298 Section 70.2: Optional Parameters ...... 300 Section 70.3: Passing Arguments by Reference ...... 300 Section 70.4: Basic Function Usage ...... 301 Section 70.5: Function Scope ...... 301 Chapter 71: Create PDF files in PHP ...... 301 Section 71.1: Getting Started with PDFlib ...... 301 Chapter 72: How to Detect Client IP Address ...... 302 Section 72.1: Proper use of HTTP_X_FORWARDED_FOR ...... 302 Chapter 73: YAML in PHP ...... 303 Section 73.1: Installing YAML extension ...... 303 Section 73.2: Using YAML to store application configuration ...... 303 Chapter 74: Image Processing with GD ...... 304 Section 74.1: Image output ...... 304 Section 74.2: Creating an image ...... 306 Section 74.3: Image Cropping and Resizing ...... 306 Chapter 75: Multiprocessing ...... 309 Section 75.1: Multiprocessing using built-in fork functions ...... 309 Section 75.2: Creating child process using fork ...... 309 Section 75.3: Inter-Process Communication ...... 310 Chapter 76: SOAP Server ...... 310 Section 76.1: Basic SOAP Server ...... 310 Chapter 77: Machine learning ...... 311 Section 77.1: Classification using PHP-ML ...... 311 Section 77.2: Regression ...... 312 Section 77.3: Clustering ...... 314 Chapter 78: Cache ...... 315 Section 78.1: Caching using memcache ...... 315 Section 78.2: Cache Using APC Cache ...... 316 Chapter 79: Streams ...... 317 Section 79.1: Registering a stream wrapper ...... 317 Chapter 80: Array iteration ...... 318 Section 80.1: Iterating multiple arrays together ...... 318 Section 80.2: Using an incremental index ...... 319 Section 80.3: Using internal array pointers ...... 320 Section 80.4: Using foreach ...... 320 Section 80.5: Using ArrayObject Iterator ...... 322 Chapter 81: Cryptography ...... 322 Section 81.1: Symmetric Encryption and Decryption of large Files with OpenSSL ...... 322 Section 81.2: Symmetric Cipher ...... 324 Chapter 82: PDO ...... 324 Section 82.1: Preventing SQL injection with Parameterized Queries ...... 325 Section 82.2: Basic PDO Connection and Retrieval ...... 326 Section 82.3: Database Transactions with PDO ...... 326 Section 82.4: PDO: connecting to MySQL/MariaDB server ...... 329 Section 82.5: PDO: Get number of aected rows by a query ...... 330 Section 82.6: PDO::lastInsertId() ...... 330 Chapter 83: SQLite3 ...... 331 Section 83.1: SQLite3 Quickstart Tutorial ...... 331 Section 83.2: Querying a database ...... 332 Section 83.3: Retrieving only one result ...... 332 Chapter 84: Sockets ...... 333 Section 84.1: TCP client socket ...... 333 Section 84.2: TCP server socket ...... 334 Section 84.3: UDP server socket ...... 334 Section 84.4: Handling socket errors ...... 335 Chapter 85: Outputting the Value of a Variable ...... 335 Section 85.1: echo and print ...... 335 Section 85.2: Outputting a structured view of arrays and objects ...... 336 Section 85.3: String concatenation with echo ...... 338 Section 85.4: printf vs sprintf ...... 339 Section 85.5: Outputting large integers ...... 340 Section 85.6: Output a Multidimensional Array with index and value and print into the table ...... 340 Chapter 86: String formatting ...... 341 Section 86.1: String interpolation ...... 341 Section 86.2: Extracting/replacing substrings ...... 342 Chapter 87: Compile PHP Extensions ...... 343 Section 87.1: Compiling on Linux ...... 343 Chapter 88: mongo-php ...... 344 Section 88.1: Everything in between MongoDB and Php ...... 344 Chapter 89: Manipulating an Array ...... 346 Section 89.1: Filtering an array ...... 346 Section 89.2: Removing elements from an array ...... 347 Section 89.3: Sorting an Array ...... 348 Section 89.4: Whitelist only some array keys ...... 352 Section 89.5: Adding element to start of array ...... 353 Section 89.6: Exchange values with keys ...... 353 Section 89.7: Merge two arrays into one array ...... 354 Chapter 90: Executing Upon an Array ...... 354 Section 90.1: Applying a function to each element of an array ...... 354 Section 90.2: Split array into chunks ...... 355 Section 90.3: Imploding an array into string ...... 356 Section 90.4: "Destructuring" arrays using list() ...... 356 Section 90.5: array_reduce ...... 357 Section 90.6: Push a Value on an Array ...... 358 Chapter 91: Processing Multiple Arrays Together ...... 358 Section 91.1: Array intersection ...... 358 Section 91.2: Merge or concatenate arrays ...... 359 Section 91.3: Changing a multidimensional array to associative array ...... 360 Section 91.4: Combining two arrays (keys from one, values from another) ...... 360 Chapter 92: SPL data structures ...... 360 Section 92.1: SplFixedArray ...... 360 Chapter 93: Comments ...... 364 Section 93.1: Single Line Comments ...... 364 Section 93.2: Multi Line Comments ...... 364 Chapter 94: IMAP ...... 364 Section 94.1: Connecting to a mailbox ...... 364 Section 94.2: Install IMAP extension ...... 365 Section 94.3: List all folders in the mailbox ...... 365 Section 94.4: Finding messages in the mailbox ...... 366 Chapter 95: Using Redis with PHP ...... 367 Section 95.1: Connecting to a Redis instance ...... 367 Section 95.2: Installing PHP Redis on Ubuntu ...... 368 Section 95.3: Executing Redis commands in PHP ...... 368 Chapter 96: Imagick ...... 368 Section 96.1: First Steps ...... 368 Section 96.2: Convert Image into base64 String ...... 369 Chapter 97: SimpleXML ...... 369 Section 97.1: Loading XML data into simplexml ...... 369 Chapter 98: HTTP Authentication ...... 370 Section 98.1: Simple authenticate ...... 370 Chapter 99: Recipes ...... 370 Section 99.1: Create a site visit counter ...... 370 Chapter 100: BC Math (Binary Calculator) ...... 371 Section 100.1: Using bcmath to read/write a binary long on 32-bit system ...... 372 Section 100.2: Comparison between BCMath and float arithmetic operations ...... 372 Chapter 101: Docker deployment ...... 373 Section 101.1: Get docker image for php ...... 373 Section 101.2: Writing dockerfile ...... 373 Section 101.3: Building image ...... 374 Section 101.4: Starting application container ...... 374 Chapter 102: WebSockets ...... 374 Section 102.1: Simple TCP/IP server ...... 374 Chapter 103: APCu ...... 375 Section 103.1: Iterating over Entries ...... 376 Section 103.2: Simple storage and retrieval ...... 376 Section 103.3: Store information ...... 376 Chapter 104: Design Patterns ...... 376 Section 104.1: Method Chaining in PHP ...... 376 Chapter 105: Secure Remeber Me ...... 378 Section 105.1: “Keep Me Logged In” - the best approach ...... 378 Chapter 106: php mysqli aected rows returns 0 when it should return a positive integer ...... 378 Chapter 107: PHP Built in server ...... 378 Section 107.1: Running the built in server ...... 379 Section 107.2: built in server with specific directory and router script ...... 379 Chapter 108: How to break down an URL ...... 379 Section 108.1: Using parse_url() ...... 379 Section 108.2: Using explode() ...... 380 Section 108.3: Using basename() ...... 381 Chapter 109: PSR ...... 381 Section 109.1: PSR-4: Autoloader ...... 381 Section 109.2: PSR-1: Basic Coding Standard ...... 382 Credits ...... 383 You may also like ...... 391 About
Please feel free to share this PDF with anyone for free, latest version of this book can be downloaded from: http://GoalKicker.com/PHPBook
Important notice: These Complete PHP Tips & Secrets for Professionals series are compiled from Stack Overflow Documentation via Archive.org, the content is written by the beautiful people at Stack Overflow, text content is released under Creative Commons BY-SA, see credits at the end of this book whom contributed to the various chapters. Images may be copyright of their respective owners unless otherwise specified
This book creation is not affiliated with PHP group(s) nor Stack Overflow, and all terms and trademarks belong to their respective company owners
The information presented in this book is not guaranteed to be correct nor accurate, use at your own risk
Send feedback and corrections to [email protected]
Complete PHP Tips & Secrets for Professionals 1 Chapter 1: Getting started with PHP
PHP 7.x Version Supported Until Release Date 7.1 2019-12-01 2016-12-01 7.0 2018-12-03 2015-12-03 PHP 5.x Version Supported Until Release Date 5.6 2018-12-31 2014-08-28 5.5 2016-07-21 2013-06-20 5.4 2015-09-03 2012-03-01 5.3 2014-08-14 2009-06-30 5.2 2011-01-06 2006-11-02 5.1 2006-08-24 2005-11-24 5.0 2005-09-05 2004-07-13 PHP 4.x Version Supported Until Release Date 4.4 2008-08-07 2005-07-11 4.3 2005-03-31 2002-12-27 4.2 2002-09-06 2002-04-22 4.1 2002-03-12 2001-12-10 4.0 2001-06-23 2000-05-22 Legacy Versions Version Supported Until Release Date 3.0 2000-10-20 1998-06-06 2.0 1997-11-01 1.0 1995-06-08 Section 1.1: HTML output from web server
PHP can be used to add content to HTML files. While HTML is processed directly by a web browser, PHP scripts are executed by a web server and the resulting HTML is sent to the browser.
The following HTML markup contains a PHP statement that will add Hello World! to the output:
When this is saved as a PHP script and executed by a web server, the following HTML will be sent to the user's browser:
Hello world!
Complete PHP Tips & Secrets for Professionals 2 PHP 5.x Version≥5.4 echo also has a shortcut syntax, which lets you immediately print a value. Prior to PHP 5.4.0, this short syntax only works with the short_open_tag configuration setting enabled.
For example, consider the following code:
Its output is identical to the output of the following:
In real-world applications, all data output by PHP to an HTML page should be properly escaped to prevent XSS (Cross-site scripting) attacks or text corruption.
See also: Strings and PSR-1, which describes best practices, including the proper use of short tags (). Section 1.2: Hello, World!
The most widely used language construct to print output in PHP is echo: echo "Hello, World!\n";
Alternatively, you can also use print: print "Hello, World!\n";
Both statements perform the same function, with minor differences:
echo has a void return, whereas print returns an int with a value of 1 echo can take multiple arguments (without parentheses only), whereas print only takes one argument echo is slightly faster than print
Both echo and print are language constructs, not functions. That means they do not require parentheses around their arguments. For cosmetic consistency with functions, parentheses can be included. Extensive examples of the use of echo and print are available elsewhere.
C-style printf and related functions are available as well, as in the following example: printf("%s\n", "Hello, World!");
See Outputting the value of a variable for a comprehensive introduction of outputting variables in PHP. Section 1.3: Non-HTML output from web server
In some cases, when working with a web server, overriding the web server's default content type may be required. There may be cases where you need to send data as plain text, JSON, or XML, for example.
The header() function can send a raw HTTP header. You can add the Content-Type header to notify the browser of the content we are sending.
Consider the following code, where we set Content-Type as text/plain: header("Content-Type: text/plain"); echo "Hello World";
This will produce a plain text document with the following content:
Complete PHP Tips & Secrets for Professionals 3 Hello World
To produce JSON content, use the application/json content type instead: header("Content-Type: application/json");
// Create a PHP data array. $data = ["response" => "Hello World"];
// json_encode will convert it to a valid JSON string. echo json_encode($data);
This will produce a document of type application/json with the following content:
{"response":"Hello World"}
Note that the header() function must be called before PHP produces any output, or the web server will have already sent headers for the response. So, consider the following code:
// Error: We cannot send any output before the headers echo "Hello";
// All headers must be sent before ANY PHP output header("Content-Type: text/plain"); echo "World";
This will produce a warning:
Warning: Cannot modify header information - headers already sent by (output started at /dir/example.php:2) in /dir/example.php on line 3
When using header(), its output needs to be the first byte that's sent from the server. For this reason it's important to not have empty lines or spaces in the beginning of the file before the PHP opening tag from files that contain only PHP and from blocks of PHP code at the very end of a file.
View the output buffering section to learn how to 'catch' your content into a variable to output later, for example, after outputting headers. Section 1.4: PHP built-in server
PHP 5.4+ comes with a built-in development server. It can be used to run applications without having to install a production HTTP server such as nginx or Apache. The built-in server is only designed to be used for development and testing purposes.
It can be started by using the -S flag: php -S
1. Create an index.php file containing:
2. Run the command php -S localhost:8080 from the command line. Do not include http://. This will start a web server listening on port 8080 using the current directory that you are in as the document root.
Complete PHP Tips & Secrets for Professionals 4 3. Open the browser and navigate to http://localhost:8080. You should see your "Hello World" page.
Configuration
To override the default document root (i.e. the current directory), use the -t flag: php -S
E.g. if you have a public/ directory in your project you can serve your project from that directory using php -S localhost:8080 -t public/.
Logs
Every time a request is made from the development server, a log entry like the one below is written to the command line.
[Mon Aug 15 18:20:19 2016] ::1:52455 [200]: / Section 1.5: PHP CLI
PHP can also be run from command line directly using the CLI (Command Line Interface).
CLI is basically the same as PHP from web servers, except some differences in terms of standard input and output.
Triggering
The PHP CLI allows four ways to run PHP code:
1. Standard input. Run the php command without any arguments, but pipe PHP code into it: echo ' echo "Hello world!"; Hello world!
Output
All functions or controls that produce HTML output in web server PHP can be used to produce output in the stdout stream (file descriptor 1), and all actions that produce output in error logs in web server PHP will produce output in the stderr stream (file descriptor 2).
Example.php Stdout 6 Shell command line $ php Example.php 2>stderr.log >stdout.log;\ > echo STDOUT; cat stdout.log; echo;\ > echo STDERR; cat stderr.log\
Complete PHP Tips & Secrets for Professionals 5 STDOUT Stdout 1 Stdout 3
STDERR Stderr 4 PHP Notice: Stderr 2 in /Example.php on line 3 PHP Fatal error: Uncaught RuntimeException: Stderr 5 in /Example.php:6 Stack trace: #0 {main} thrown in /Example.php on line 6 Input
See: Command Line Interface (CLI) Section 1.6: Instruction Separation
Just like most other C-style languages, each statement is terminated with a semicolon. Also, a closing tag is used to terminate the last line of code of the PHP block.
If the last line of PHP code ends with a semicolon, the closing tag is optional if there is no code following that final line of code. For example, we can leave out the closing tag after echo "No error"; in the following example:
However, if there is any other code following your PHP code block, the closing tag is no longer optional:
We can also leave out the semicolon of the last statement in a PHP code block if that code block has a closing tag:
It is generally recommended to always use a semicolon and use a closing tag for every PHP code block except the last PHP code block, if no more code follows that PHP code block.
So, your code should basically look like this:
Some HTML code goes here
Some HTML code goes here
Complete PHP Tips & Secrets for Professionals 6 echo "Here as well!"; echo "Here as well!"; echo "Here we use a semicolon but leave out the closing tag"; Section 1.7: PHP Tags
There are three kinds of tags to denote PHP blocks in a file. The PHP parser is looking for the opening and (if present) closing tags to delimit the code to interpret.
Standard Tags
These tags are the standard method to embed PHP code in a file.
PHP 5.x Version≥5.4 Echo Tags
These tags are available in all PHP versions, and since PHP 5.4 are always enabled. In previous versions, echo tags could only be enabled in conjunction with short tags.
Short Tags
You can disable or enable these tags with the option short_open_tag.
Short tags:
are disallowed in all major PHP coding standards are discouraged in the official documentation are disabled by default in most distributions interfere with inline XML's processing instructions are not accepted in code submissions by most open source projects
PHP 5.x Version≤5.6 ASP Tags
By enabling the asp_tags option, ASP-style tags can be used.
<% echo "Hello World"; %>
These are an historic quirk and should never be used. They were removed in PHP 7.0.
Chapter 2: Variables
$variable = 'value'; // Assign general variable $object->property = 'value'; // Assign an object property ClassName::$property = 'value'; // Assign a static class property $array[0] = 'value'; // Assign a value to an index of an array
Complete PHP Tips & Secrets for Professionals 7 $array[] = 'value'; // Push an item at the end of an array $array['key'] = 'value'; // Assign an array value echo $variable; // Echo (print) a variable value some_function($variable); // Use variable as function parameter unset($variable); // Unset a variable $$variable = 'value'; // Assign to a variable variable isset($variable); // Check if a variable is set or not empty($variable); // Check if a variable is empty or not Section 2.1: Accessing A Variable Dynamically By Name (Variable variables)
Variables can be accessed via dynamic variable names. The name of a variable can be stored in another variable, allowing it to be accessed dynamically. Such variables are known as variable variables.
To turn a variable into a variable variable, you put an extra $ put in front of your variable.
$variableName = 'foo'; $foo = 'bar';
// The following are all equivalent, and all output "bar": echo $foo; echo ${$variableName}; echo $$variableName;
//similarly, $variableName = 'foo'; $$variableName = 'bar';
// The following statements will also output 'bar' echo $foo; echo $$variableName; echo ${$variableName};
Variable variables are useful for mapping function/method calls: function add($a, $b) { return $a + $b; }
$funcName = 'add'; echo $funcName(1, 2); // outputs 3
This becomes particularly helpful in PHP classes: class myClass { public function __construct() { $functionName = 'doSomething'; $this->$functionName('Hello World'); }
private function doSomething($string) { echo $string; // Outputs "Hello World" } }
It is possible, but not required to put $variableName between {}:
${$variableName} = $value;
Complete PHP Tips & Secrets for Professionals 8 The following examples are both equivalent and output "baz":
$fooBar = 'baz'; $varPrefix = 'foo'; echo $fooBar; // Outputs "baz" echo ${$varPrefix . 'Bar'}; // Also outputs "baz"
Using {} is only mandatory when the name of the variable is itself an expression, like this:
${$variableNamePart1 . $variableNamePart2} = $value;
It is nevertheless recommended to always use {}, because it's more readable.
While it is not recommended to do so, it is possible to chain this behavior:
$$$$$$$$DoNotTryThisAtHomeKids = $value;
It's important to note that the excessive usage of variable variables is considered a bad practice by many developers. Since they're not well-suited for static analysis by modern IDEs, large codebases with many variable variables (or dynamic method invocations) can quickly become difficult to maintain.
Differences between PHP5 and PHP7
Another reason to always use {} or (), is that PHP5 and PHP7 have a slightly different way of dealing with dynamic variables, which results in a different outcome in some cases.
In PHP7, dynamic variables, properties, and methods will now be evaluated strictly in left-to-right order, as opposed to the mix of special cases in PHP5. The examples below show how the order of evaluation has changed.
Case 1 : $$foo['bar']['baz']
PHP5 interpretation : ${$foo['bar']['baz']} PHP7 interpretation : ($$foo)['bar']['baz']
Case 2 : $foo->$bar['baz']
PHP5 interpretation : $foo->{$bar['baz']} PHP7 interpretation : ($foo->$bar)['baz']
Case 3 : $foo->$bar['baz']()
PHP5 interpretation : $foo->{$bar['baz']}() PHP7 interpretation : ($foo->$bar)['baz']()
Case 4 : Foo::$bar['baz']()
PHP5 interpretation : Foo::{$bar['baz']}() PHP7 interpretation : (Foo::$bar)['baz']() Section 2.2: Data Types
There are different data types for different purposes. PHP does not have explicit type definitions, but the type of a variable is determined by the type of the value that is assigned, or by the type that it is casted to. This is a brief overview about the types, for a detailed documentation and examples, see the PHP types topic.
There are following data types in PHP: null, boolean, integer, float, string, object, resource and array.
Null
Complete PHP Tips & Secrets for Professionals 9 Null can be assigned to any variable. It represents a variable with no value.
$foo = null;
This invalidates the variable and it's value would be undefined or void if called. The variable is cleared from memory and deleted by the garbage collector.
Boolean
This is the simplest type with only two possible values.
$foo = true; $bar = false;
Booleans can be used to control the flow of code.
$foo = true; if ($foo) { echo "true"; } else { echo "false"; } Integer
An integer is a whole number positive or negative. It can be in used with any number base. The size of an integer is platform-dependent. PHP does not support unsigned integers.
$foo = -3; // negative $foo = 0; // zero (can also be null or false (as boolean) $foo = 123; // positive decimal $bar = 0123; // octal = 83 decimal $bar = 0xAB; // hexadecimal = 171 decimal $bar = 0b1010; // binary = 10 decimal var_dump(0123, 0xAB, 0b1010); // output: int(83) int(171) int(10) Float
Floating point numbers, "doubles" or simply called "floats" are decimal numbers.
$foo = 1.23; $foo = 10.0; $bar = -INF; $bar = NAN; Array
An array is like a list of values. The simplest form of an array is indexed by integer, and ordered by the index, with the first element lying at index 0.
$foo = array(1, 2, 3); // An array of integers $bar = ["A", true, 123 => 5]; // Short array syntax, PHP 5.4+ echo $bar[0]; // Returns "A" echo $bar[1]; // Returns true echo $bar[123]; // Returns 5 echo $bar[1234]; // Returns null
Arrays can also associate a key other than an integer index to a value. In PHP, all arrays are associative arrays behind the scenes, but when we refer to an 'associative array' distinctly, we usually mean one that contains one or more keys that aren't integers.
Complete PHP Tips & Secrets for Professionals 10 $array = array(); $array["foo"] = "bar"; $array["baz"] = "quux"; $array[42] = "hello"; echo $array["foo"]; // Outputs "bar" echo $array["bar"]; // Outputs "quux" echo $array[42]; // Outputs "hello" String
A string is like an array of characters.
$foo = "bar";
Like an array, a string can be indexed to return its individual characters:
$foo = "bar"; echo $foo[0]; // Prints 'b', the first character of the string in $foo. Object
An object is an instance of a class. Its variables and methods can be accessed with the -> operator.
$foo = new stdClass(); // create new object of class stdClass, which a predefined, empty class $foo->bar = "baz"; echo $foo->bar; // Outputs "baz" // Or we can cast an array to an object: $quux = (object) ["foo" => "bar"]; echo $quux->foo; // This outputs "bar". Resource
Resource variables hold special handles to opened files, database connections, streams, image canvas areas and the like (as it is stated in the manual).
$fp = fopen('file.ext', 'r'); // fopen() is the function to open a file on disk as a resource. var_dump($fp); // output: resource(2) of type (stream)
To get the type of a variable as a string, use the gettype() function: echo gettype(1); // outputs "integer" echo gettype(true); // "boolean" Section 2.3: Global variable best practices
We can illustrate this problem with the following pseudo-code function foo() { global $bob; $bob->doSomething(); }
Your first question here is an obvious one
Where did $bob come from?
Are you confused? Good. You've just learned why globals are confusing and considered a bad practice.
If this were a real program, your next bit of fun is to go track down all instances of $bob and hope you find the right one (this gets worse if $bob is used everywhere). Worse, if someone else goes and defines $bob (or you forgot and reused that variable) your code can break (in the above code example, having the wrong object, or no object at all, would cause a fatal error).
Complete PHP Tips & Secrets for Professionals 11 Since virtually all PHP programs make use of code like include('file.php'); your job maintaining code like this becomes exponentially harder the more files you add.
Also, this makes the task of testing your applications very difficult. Suppose you use a global variable to hold your database connection:
$dbConnector = new DBConnector(...); function doSomething() { global $dbConnector; $dbConnector->execute("..."); }
In order to unit test this function, you have to override the global $dbConnector variable, run the tests and then reset it to its original value, which is very bug prone:
/** * @test */ function testSomething() { global $dbConnector; $bkp = $dbConnector; // Make backup $dbConnector = Mock::create('DBConnector'); // Override assertTrue(foo()); $dbConnector = $bkp; // Restore }
How do we avoid Globals?
The best way to avoid globals is a philosophy called Dependency Injection. This is where we pass the tools we need into the function or class. function foo(\Bar $bob) { $bob->doSomething(); }
This is much easier to understand and maintain. There's no guessing where $bob was set up because the caller is responsible for knowing that (it's passing us what we need to know). Better still, we can use type declarations to restrict what's being passed.
So we know that $bob is either an instance of the Bar class, or an instance of a child of Bar, meaning we know we can use the methods of that class. Combined with a standard autoloader (available since PHP 5.3), we can now go track down where Bar is defined. PHP 7.0 or later includes expanded type declarations, where you can also use scalar types (like int or string).
Version=4.1
Superglobal variables
Super globals in PHP are predefined variables, which are always available, can be accessed from any scope throughout the script.
There is no need to do global $variable; to access them within functions/methods, classes or files.
These PHP superglobal variables are listed below:
$GLOBALS $_SERVER $_REQUEST $_POST $_GET $_FILES $_ENV $_COOKIE $_SESSION
Complete PHP Tips & Secrets for Professionals 12 Section 2.4: Default values of uninitialized variables
Although not necessary in PHP however it is a very good practice to initialize variables. Uninitialized variables have a default value of their type depending on the context in which they are used:
Unset AND unreferenced var_dump($unset_var); // outputs NULL
Boolean echo($unset_bool ? "true\n" : "false\n"); // outputs 'false'
String
$unset_str .= 'abc'; var_dump($unset_str); // outputs 'string(3) "abc"'
Integer
$unset_int += 25; // 0 + 25 => 25 var_dump($unset_int); // outputs 'int(25)'
Float/double
$unset_float += 1.25; var_dump($unset_float); // outputs 'float(1.25)'
Array
$unset_arr[3] = "def"; var_dump($unset_arr); // outputs array(1) { [3]=> string(3) "def" }
Object
$unset_obj->foo = 'bar'; var_dump($unset_obj); // Outputs: object(stdClass)#1 (1) { ["foo"]=> string(3) "bar" }
Relying on the default value of an uninitialized variable is problematic in the case of including one file into another which uses the same variable name. Section 2.5: Variable Value Truthiness and Identical Operator
In PHP, variable values have an associated "truthiness" so even non-boolean values will equate to true or false. This allows any variable to be used in a conditional block, e.g. if ($var == true) { /* explicit version */ } if ($var) { /* $var == true is implicit */ }
Here are some fundamental rules for different types of variable values:
Strings with non-zero length equate to true including strings containing only whitepace such as ' '. Empty strings '' equate to false.
$var = ''; $var_is_true = ($var == true); // false $var_is_false = ($var == false); // true
$var = ' '; $var_is_true = ($var == true); // true
Complete PHP Tips & Secrets for Professionals 13 $var_is_false = ($var == false); // false
Integers equate to true if they are nonzero, while zero equates to false.
$var = -1; $var_is_true = ($var == true); // true $var = 99; $var_is_true = ($var == true); // true $var = 0; $var_is_true = ($var == true); // false
null equates to false
$var = null; $var_is_true = ($var == true); // false $var_is_false = ($var == false); // true
Empty strings '' and string zero '0' equate to false.
$var = ''; $var_is_true = ($var == true); // false $var_is_false = ($var == false); // true
$var = '0'; $var_is_true = ($var == true); // false $var_is_false = ($var == false); // true
Floating-point values equate to true if they are nonzero, while zero values equates to false. NAN (PHP's Not-a-Number) equates to true, i.e. NAN == true is true. This is because NAN is a nonzero floating-point value. Zero-values include both +0 and -0 as defined by IEEE 754. PHP does not distinguish between +0 and -0 in its double-precision floating-point, i.e. floatval('0') == floatval('-0') is true. In fact, floatval('0') === floatval('-0'). Additionally, both floatval('0') == false and floatval('-0') == false.
$var = NAN; $var_is_true = ($var == true); // true $var_is_false = ($var == false); // false
$var = floatval('-0'); $var_is_true = ($var == true); // false $var_is_false = ($var == false); // true
$var = floatval('0') == floatval('-0'); $var_is_true = ($var == true); // false $var_is_false = ($var == false); // true
IDENTICAL OPERATOR
In the PHP Documentation for Comparison Operators, there is an Identical Operator ===. This operator can be used to check whether a variable is identical to a reference value:
$var = null; $var_is_null = $var === null; // true $var_is_true = $var === true; // false $var_is_false = $var === false; // false
It has a corresponding not identical operator !==:
$var = null; $var_is_null = $var !== null; // false $var_is_true = $var !== true; // true
Complete PHP Tips & Secrets for Professionals 14 $var_is_false = $var !== false; // true
The identical operator can be used as an alternative to language functions like is_null().
USE CASE WITH strpos()
The strpos($haystack, $needle) language function is used to locate the index at which $needle occurs in $haystack, or whether it occurs at all. The strpos() function is case sensitive; if case-insensitive find is what you need you can go with stripos($haystack, $needle)
The strpos & stripos function also contains third parameter offset (int) which if specified, search will start this number of characters counted from the beginning of the string. Unlike strrpos and strripos, the offset cannot be negative
The function can return:
0 if $needle is found at the beginning of $haystack; a non-zero integer specifying the index if $needle is found somewhere other than the beginning in $haystack; and value false if $needle is not found anywhere in $haystack.
Because both 0 and false have truthiness false in PHP but represent distinct situations for strpos(), it is important to distinguish between them and use the identical operator === to look exactly for false and not just a value that equates to false.
$idx = substr($haystack, $needle); if ($idx === false) { // logic for when $needle not found in $haystack } else { // logic for when $needle found in $haystack }
Alternatively, using the not identical operator:
$idx = substr($haystack, $needle); if ($idx !== false) { // logic for when $needle found in $haystack } else { // logic for when $needle not found in $haystack } Chapter 3: Arrays
$array = array('Value1', 'Value2', 'Value3'); // Keys default to 0, 1, 2, ..., $array = array('Value1', 'Value2', ); // Optional trailing comma $array = array('key1' => 'Value1', 'key2' => 'Value2', ); // Explicit keys $array = array('key1' => 'Value1', 'Value2', ); // Array ( ['key1'] => Value1 [1] => 'Value2') $array = ['key1' => 'Value1', 'key2' => 'Value2', ]; // PHP 5.4+ shorthand $array[] = 'ValueX'; // Append 'ValueX' to the end of the array $array['keyX'] = 'ValueX'; // Assign 'valueX' to key 'keyX' $array += ['keyX' => 'valueX', 'keyY' => 'valueY']; // Adding/Overwrite elements on an existing array
Complete PHP Tips & Secrets for Professionals 15 Parameter Detail The key is the unique identifier and index of an array. It may be a string or an integer. Therefore, Key valid keys would be 'foo', '5', 10, 'a2b', ... For each key there is a corresponding value (null otherwise and a notice is emitted upon access). The Value value has no restrictions on the input type.
An array is a data structure that stores an arbitrary number of values in a single value. An array in PHP is actually an ordered map, where map is a type that associates values to keys. Section 3.1: Initializing an Array
An array can be initialized empty:
// An empty array $foo = array();
// Shorthand notation available since PHP 5.4 $foo = [];
An array can be initialized and preset with values:
// Creates a simple array with three strings $fruit = array('apples', 'pears', 'oranges');
// Shorthand notation available since PHP 5.4 $fruit = ['apples', 'pears', 'oranges'];
An array can also be initialized with custom indexes (also called an associative array):
// A simple associative array $fruit = array( 'first' => 'apples', 'second' => 'pears', 'third' => 'oranges' );
// Key and value can also be set as follows $fruit['first'] = 'apples';
// Shorthand notation available since PHP 5.4 $fruit = [ 'first' => 'apples', 'second' => 'pears', 'third' => 'oranges' ];
If the variable hasn't been used before, PHP will create it automatically. While convenient, this might make the code harder to read:
$foo[] = 1; // Array( [0] => 1 ) $bar[][] = 2; // Array( [0] => Array( [0] => 2 ) )
The index will usually continue where you left off. PHP will try to use numeric strings as integers:
$foo = [2 => 'apple', 'melon']; // Array( [2] => apple, [3] => melon ) $foo = ['2' => 'apple', 'melon']; // same as above
Complete PHP Tips & Secrets for Professionals 16 $foo = [2 => 'apple', 'this is index 3 temporarily', '3' => 'melon']; // same as above! The last entry will overwrite the second!
To initialize an array with fixed size you can use SplFixedArray:
$array = new SplFixedArray(3);
$array[0] = 1; $array[1] = 2; $array[2] = 3; $array[3] = 4; // RuntimeException
// Increase the size of the array to 10 $array->setSize(10);
Note: An array created using SplFixedArray has a reduced memory footprint for large sets of data, but the keys must be integers.
To initialize an array with a dynamic size but with n non empty elements (e.g. a placeholder) you can use a loop as follows:
$myArray = array(); $sizeOfMyArray = 5; $fill = 'placeholder'; for ($i = 0; $i < $sizeOfMyArray; $i++) { $myArray[] = $fill; }
// print_r($myArray); results in the following: // Array ( [0] => placeholder [1] => placeholder [2] => placeholder [3] => placeholder [4] => placeholder )
If all your placeholders are the same then you can also create it using the function array_fill(): array array_fill ( int $start_index , int $num , mixed $value )
This creates and returns an array with num entries of value, keys starting at start_index.
Note: If the start_index is negative it will start with the negative index and continue from 0 for the following elements.
$a = array_fill(5, 6, 'banana'); // Array ( [5] => banana, [6] => banana, ..., [10] => banana) $b = array_fill(-2, 4, 'pear'); // Array ( [-2] => pear, [0] => pear, ..., [2] => pear)
Conclusion: With array_fill() you are more limited for what you can actually do. The loop is more flexible and opens you a wider range of opportunities.
Whenever you want an array filled with a range of numbers (e.g. 1-4) you could either append every single element to an array or use the range() function: array range ( mixed $start , mixed $end [, number $step = 1 ] )
This function creates an array containing a range of elements. The first two parameters are required, where they set the start and end points of the (inclusive) range. The third parameter is optional and defines the size of the
Complete PHP Tips & Secrets for Professionals 17 steps being taken. Creating a range from 0 to 4 with a stepsize of 1, the resulting array would consist of the following elements: 0, 1, 2, 3, and 4. If the step size is increased to 2 (i.e. range(0, 4, 2)) then the resulting array would be: 0, 2, and 4.
$array = []; $array_with_range = range(1, 4); for ($i = 1; $i <= 4; $i++) { $array[] = $i; } print_r($array); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) print_r($array_with_range); // Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 ) range can work with integers, floats, booleans (which become casted to integers), and strings. Caution should be taken, however, when using floats as arguments due to the floating point precision problem. Section 3.2: Check if key exists
Use array_key_exists() or isset() or !empty():
$map = [ 'foo' => 1, 'bar' => null, 'foobar' => '', ]; array_key_exists('foo', $map); // true isset($map['foo']); // true !empty($map['foo']); // true array_key_exists('bar', $map); // true isset($map['bar']); // false !empty($map['bar']); // false
Note that isset() treats a null valued element as non-existent. Whereas !empty() does the same for any element that equals false (using a weak comparision; for example, null, '' and 0 are all treated as false by !empty()). While isset($map['foobar']); is true, !empty($map['foobar']) is false. This can lead to mistakes (for example, it is easy to forget that the string '0' is treated as false) so use of !empty() is often frowned upon.
Note also that isset() and !empty() will work (and return false) if $map is not defined at all. This makes them somewhat error-prone to use:
// Note "long" vs "lang", a tiny typo in the variable name. $my_array_with_a_long_name = ['foo' => true]; array_key_exists('foo', $my_array_with_a_lang_name); // shows a warning isset($my_array_with_a_lang_name['foo']); // returns false
You can also check for ordinal arrays:
$ord = ['a', 'b']; // equivalent to [0 => 'a', 1 => 'b'] array_key_exists(0, $ord); // true array_key_exists(2, $ord); // false
Note that isset() has better performance than array_key_exists() as the latter is a function and the former a language construct.
You can also use key_exists(), which is an alias for array_key_exists().
Complete PHP Tips & Secrets for Professionals 18 Section 3.3: Validating the array type
The function is_array() returns true if a variable is an array.
$integer = 1337; $array = [1337, 42]; is_array($integer); // false is_array($array); // true
You can type hint the array type in a function to enforce a parameter type; passing anything else will result in a fatal error. function foo (array $array) { /* $array is an array */ }
You can also use the gettype() function.
$integer = 1337; $array = [1337, 42]; gettype($integer) === 'array'; // false gettype($array) === 'array'; // true Section 3.4: Creating an array of variables
$username = 'Hadibut'; $email = '[email protected]';
$variables = compact('username', 'email'); // $variables is now ['username' => 'Hadibut', 'email' => '[email protected]']
This method is often used in frameworks to pass an array of variables between two components. Section 3.5: Checking if a value exists in array
The function in_array() returns true if an item exists in an array.
$fruits = ['banana', 'apple'];
$foo = in_array('banana', $fruits); // $foo value is true
$bar = in_array('orange', $fruits); // $bar value is false
You can also use the function array_search() to get the key of a specific item in an array.
$userdb = ['Sandra Shush', 'Stefanie Mcmohn', 'Michael']; $pos = array_search('Stefanie Mcmohn', $userdb); if ($pos !== false) { echo "Stefanie Mcmohn found at $pos"; } PHP 5.x Version≥5.5
In PHP 5.5 and later you can use array_column() in conjunction with array_search().
This is particularly useful for checking if a value exists in an associative array:
$userdb = [ [ "uid" => '100',
Complete PHP Tips & Secrets for Professionals 19 "name" => 'Sandra Shush', "url" => 'urlof100', ], [ "uid" => '5465', "name" => 'Stefanie Mcmohn', "pic_square" => 'urlof100', ], [ "uid" => '40489', "name" => 'Michael', "pic_square" => 'urlof40489', ] ];
$key = array_search(40489, array_column($userdb, 'uid')); Section 3.6: ArrayAccess and Iterator Interfaces
Another useful feature is accessing your custom object collections as arrays in PHP. There are two interfaces available in PHP (>=5.0.0) core to support this: ArrayAccess and Iterator. The former allows you to access your custom objects as array.
ArrayAccess
Assume we have a user class and a database table storing all the users. We would like to create a UserCollection class that will:
1. allow us to address certain user by their username unique identifier 2. perform basic (not all CRUD, but at least Create, Retrieve and Delete) operations on our users collection
Consider the following source (hereinafter we're using short array creation syntax [] available since version 5.4): class UserCollection implements ArrayAccess { protected $_conn;
protected $_requiredParams = ['username','password','email'];
public function __construct() { $config = new Configuration();
$connectionParams = [ //your connection to the database ];
$this->_conn = DriverManager::getConnection($connectionParams, $config); }
protected function _getByUsername($username) { $ret = $this->_conn->executeQuery('SELECT * FROM `User` WHERE `username` IN (?)', [$username] )->fetch();
return $ret; }
// START of methods required by ArrayAccess interface public function offsetExists($offset) { return (bool) $this->_getByUsername($offset); }
Complete PHP Tips & Secrets for Professionals 20 public function offsetGet($offset) { return $this->_getByUsername($offset); }
public function offsetSet($offset, $value) { if (!is_array($value)) { throw new \Exception('value must be an Array'); }
$passed = array_intersect(array_values($this->_requiredParams), array_keys($value)); if (count($passed) < count($this->_requiredParams)) { throw new \Exception('value must contain at least the following params: ' . implode(',', $this->_requiredParams)); } $this->_conn->insert('User', $value); }
public function offsetUnset($offset) { if (!is_string($offset)) { throw new \Exception('value must be the username to delete'); } if (!$this->offsetGet($offset)) { throw new \Exception('user not found'); } $this->_conn->delete('User', ['username' => $offset]); } // END of methods required by ArrayAccess interface } then we can :
$users = new UserCollection(); var_dump(empty($users['testuser']),isset($users['testuser'])); $users['testuser'] = ['username' => 'testuser', 'password' => 'testpassword', 'email' => '[email protected]']; var_dump(empty($users['testuser']), isset($users['testuser']), $users['testuser']); unset($users['testuser']); var_dump(empty($users['testuser']), isset($users['testuser'])); which will output the following, assuming there was no testuser before we launched the code: bool(true) bool(false) bool(false) bool(true) array(17) { ["username"]=> string(8) "testuser" ["password"]=> string(12) "testpassword" ["email"]=> string(13) "[email protected]" } bool(true) bool(false)
IMPORTANT: offsetExists is not called when you check existence of a key with array_key_exists function. So the following code will output false twice: var_dump(array_key_exists('testuser', $users));
Complete PHP Tips & Secrets for Professionals 21 $users['testuser'] = ['username' => 'testuser', 'password' => 'testpassword', 'email' => '[email protected]']; var_dump(array_key_exists('testuser', $users));
Iterator
Let's extend our class from above with a few functions from Iterator interface to allow iterating over it with foreach and while.
First, we need to add a property holding our current index of iterator, let's add it to the class properties as $_position:
// iterator current position, required by Iterator interface methods protected $_position = 1;
Second, let's add Iterator interface to the list of interfaces being implemented by our class: class UserCollection implements ArrayAccess, Iterator { then add the required by the interface functions themselves:
// START of methods required by Iterator interface public function current () { return $this->_getById($this->_position); } public function key () { return $this->_position; } public function next () { $this->_position++; } public function rewind () { $this->_position = 1; } public function valid () { return null !== $this->_getById($this->_position); } // END of methods required by Iterator interface
So all in all here is complete source of the class implementing both interfaces. Note that this example is not perfect, because the IDs in the database may not be sequential, but this was written just to give you the main idea: you can address your objects collections in any possible way by implementing ArrayAccess and Iterator interfaces: class UserCollection implements ArrayAccess, Iterator { // iterator current position, required by Iterator interface methods protected $_position = 1;
//
// START of methods required by Iterator interface public function current () { return $this->_getById($this->_position); } public function key () { return $this->_position; } public function next () { $this->_position++; } public function rewind () {
Complete PHP Tips & Secrets for Professionals 22 $this->_position = 1; } public function valid () { return null !== $this->_getById($this->_position); } // END of methods required by Iterator interface } and a foreach looping through all user objects: foreach ($users as $user) { var_dump($user['id']); } which will output something like string(2) "1" string(2) "2" string(2) "3" string(2) "4" ... Chapter 4: Functional Programming
PHP's functional programming relies on functions. Functions in PHP provide organized, reusable code to perform a set of actions. Functions simplify the coding process, prevent redundant logic, and make code easier to follow. This topic describes the declaration and utilization of functions, arguments, parameters, return statements and scope in PHP. Section 4.1: Closures
A closure is an anonymous function that can't access outside scope.
When defining an anonymous function as such, you're creating a "namespace" for that function. It currently only has access to that namespace.
$externalVariable = "Hello"; $secondExternalVariable = "Foo"; $myFunction = function() {
var_dump($externalVariable, $secondExternalVariable); // returns two error notice, since the variables aren´t defined
}
It doesn't have access to any external variables. To grant this permission for this namespace to access external variables, you need to introduce it via closures (use()).
$myFunction = function() use($externalVariable, $secondExternalVariable) { var_dump($externalVariable, $secondExternalVariable); // Hello Foo }
This is heavily attributed to PHP's tight variable scoping - If a variable isn't defined within the scope, or isn't brought in with global then it does not exist.
Also note:
Inheriting variables from the parent scope is not the same as using global variables. Global variables exist in the global scope, which is the same no matter what function is executing.
Complete PHP Tips & Secrets for Professionals 23 The parent scope of a closure is the function in which the closure was declared (not necessarily the function it was called from).
Taken from the PHP Documentation for Anonymous Functions
In PHP, closures use an early-binding approach. This means that variables passed to the closure's namespace using use keyword will have the same values when the closure was defined.
To change this behavior you should pass the variable by-reference.
$rate = .05;
// Exports variable to closure's scope $calculateTax = function ($value) use ($rate) { return $value * $rate; };
$rate = .1; print $calculateTax(100); // 5 $rate = .05;
// Exports variable to closure's scope $calculateTax = function ($value) use (&$rate) { // notice the & before $rate return $value * $rate; };
$rate = .1; print $calculateTax(100); // 10
Default arguments are not implicitly required when defining anonymous functions with/without closures.
$message = 'Im yelling at you';
$yell = function() use($message) { echo strtoupper($message); };
$yell(); // returns: IM YELLING AT YOU Section 4.2: Assignment to variables
Anonymous functions can be assigned to variables for use as parameters where a callback is expected:
$uppercase = function($data) { return strtoupper($data); };
$mixedCase = ["Hello", "World"]; $uppercased = array_map($uppercase, $mixedCase); print_r($uppercased);
These variables can also be used as standalone function calls: echo $uppercase("Hello world!"); // HELLO WORLD! Section 4.3: Objects as a function class SomeClass { public function __invoke($param1, $param2) {
Complete PHP Tips & Secrets for Professionals 24 // put your code here } }
$instance = new SomeClass(); $instance('First', 'Second'); // call the __invoke() method
An object with an __invoke method can be used exactly as any other function.
The __invoke method will have access to all properties of the object and will be able to call any methods. Section 4.4: Using outside variables
The use construct is used to import variables into the anonymous function's scope:
$divisor = 2332; $myfunction = function($number) use ($divisor) { return $number / $divisor; }; echo $myfunction(81620); //Outputs 35
Variables can also be imported by reference:
$collection = [];
$additem = function($item) use (&$collection) { $collection[] = $item; };
$additem(1); $additem(2);
//$collection is now [1,2] Section 4.5: Anonymous function
An anonymous function is just a function that doesn't have a name.
// Anonymous function function() { return "Hello World!"; };
In PHP, an anonymous function is treated like an expression and for this reason, it should be ended with a semicolon ;.
An anonymous function should be assigned to a variable.
// Anonymous function assigned to a variable $sayHello = function($name) { return "Hello $name!"; }; print $sayHello('John'); // Hello John
Or it should be passed as parameter of another function.
$users = [ ['name' => 'Alice', 'age' => 20], ['name' => 'Bobby', 'age' => 22],
Complete PHP Tips & Secrets for Professionals 25 ['name' => 'Carol', 'age' => 17] ];
// Map function applying anonymous function $userName = array_map(function($user) { return $user['name']; }, $users); print_r($usersName); // ['Alice', 'Bobby', 'Carol']
Or even been returned from another function.
Self-executing anonymous functions:
// For PHP 7.x (function () { echo "Hello world!"; })();
// For PHP 5.x call_user_func(function () { echo "Hello world!"; });
Passing an argument into self-executing anonymous functions:
// For PHP 7.x (function ($name) { echo "Hello $name!"; })('John');
// For PHP 5.x call_user_func(function ($name) { echo "Hello $name!"; }, 'John'); Section 4.6: Pure functions
A pure function is a function that, given the same input, will always return the same output and are side-effect free.
// This is a pure function function add($a, $b) { return $a + $b; }
Some side-effects are changing the filesystem, interacting with databases, printing to the screen.
// This is an impure function function add($a, $b) { echo "Adding..."; return $a + $b; } Section 4.7: Common functional methods in PHP
Mapping
Applying a function to all elements of an array : array_map('strtoupper', $array);
Complete PHP Tips & Secrets for Professionals 26 Be aware that this is the only method of the list where the callback comes first.
Reducing (or folding)
Reducing an array to a single value :
$sum = array_reduce($numbers, function ($carry, $number) { return $carry + $number; }); Filtering
Returns only the array items for which the callback returns true :
$onlyEven = array_filter($numbers, function ($number) { return ($number % 2) === 0; }); Section 4.8: Using built-in functions as callbacks
In functions taking callable as an argument, you can also put a string with PHP built-in function. It's common to use trim as array_map parameter to remove leading and trailing whitespace from all strings in the array.
$arr = [' one ', 'two ', ' three']; var_dump(array_map('trim', $arr));
// array(3) { // [0] => // string(3) "one" // [1] => // string(3) "two" // [2] => // string(5) "three" // } Section 4.9: Scope
In PHP, an anonymous function has its own scope like any other PHP function.
In JavaScript, an anonymous function can access a variable in outside scope. But in PHP, this is not permitted.
$name = 'John';
// Anonymous function trying access outside scope $sayHello = function() { return "Hello $name!"; } print $sayHello('John'); // Hello ! // With notices active, there is also an Undefined variable $name notice Section 4.10: Passing a callback function as a parameter
There are several PHP functions that accept user-defined callback functions as a parameter, such as: call_user_func(), usort() and array_map().
Depending on where the user-defined callback function was defined there are different ways to pass them:
Procedural style: function square($number) {
Complete PHP Tips & Secrets for Professionals 27 return $number * $number; }
$initial_array = [1, 2, 3, 4, 5]; $final_array = array_map('square', $initial_array); var_dump($final_array); // prints the new array with 1, 4, 9, 16, 25 Object Oriented style: class SquareHolder { function square($number) { return $number * $number; } }
$squaredHolder = new SquareHolder(); $initial_array = [1, 2, 3, 4, 5]; $final_array = array_map([$squaredHolder, 'square'], $initial_array); var_dump($final_array); // prints the new array with 1, 4, 9, 16, 25 Object Oriented style using a static method: class StaticSquareHolder { public static function square($number) { return $number * $number; } }
$initial_array = [1, 2, 3, 4, 5]; $final_array = array_map(['StaticSquareHolder', 'square'], $initial_array); // or: $final_array = array_map('StaticSquareHolder::square', $initial_array); // for PHP >= 5.2.3 var_dump($final_array); // prints the new array with 1, 4, 9, 16, 25 Chapter 5: Types Section 5.1: Type Comparison
There are two types of comparison: loose comparison with == and strict comparison with ===. Strict comparison ensures both the type and value of both sides of the operator are the same.
// Loose comparisons var_dump(1 == 1); // true var_dump(1 == "1"); // true var_dump(1 == true); // true var_dump(0 == false); // true
// Strict comparisons var_dump(1 === 1); // true var_dump(1 === "1"); // false var_dump(1 === true); // false var_dump(0 === false); // false
// Notable exception: NAN — it never is equal to anything var_dump(NAN == NAN); // false var_dump(NAN === NAN); // false
You can also use strong comparison to check if type and value don't match using !==.
Complete PHP Tips & Secrets for Professionals 28 A typical example where the == operator is not enough, are functions that can return different types, like strpos, which returns false if the searchword is not found, and the match position (int) otherwise: if(strpos('text', 'searchword') == false) // strpos returns false, so == comparison works as expected here, BUT: if(strpos('text bla', 'text') == false) // strpos returns 0 (found match at position 0) and 0==false is true. // This is probably not what you expect! if(strpos('text','text') === false) // strpos returns 0, and 0===false is false, so this works as expected. Section 5.2: Boolean
Boolean is a type, having two values, denoted as true or false.
This code sets the value of $foo as true and $bar as false:
$foo = true; $bar = false; true and false are not case sensitive, so TRUE and FALSE can be used as well, even FaLsE is possible. Using lower case is most common and recommended in most code style guides, e.g. PSR-2.
Booleans can be used in if statements like this: if ($foo) { //same as evaluating if($foo == true) echo "true"; }
Due to the fact that PHP is weakly typed, if $foo above is other than true or false, it's automatically coerced to a boolean value. The following values result in false:
a zero value: 0 (integer), 0.0 (float), or '0' (string) an empty string '' or array [] null (the content of an unset variable, or assigned to a variable)
Any other value results in true.
To avoid this loose comparison, you can enforce strong comparison using ===, which compares value and type. See Type Comparison for details.
To convert a type into boolean, you can use the (bool) or (boolean) cast before the type. var_dump((bool) "1"); //evaluates to true or call the boolval function: var_dump( boolval("1") ); //evaluates to true
Boolean conversion to a string (note that false yields an empty string): var_dump( (string) true ); // string(1) "1" var_dump( (string) false ); // string(0) ""
Boolean conversion to an integer: var_dump( (int) true ); // int(1) var_dump( (int) false ); // int(0)
Complete PHP Tips & Secrets for Professionals 29 Note that the opposite is also possible: var_dump((bool) ""); // bool(false) var_dump((bool) 1); // bool(true)
Also all non-zero will return true: var_dump((bool) -2); // bool(true) var_dump((bool) "foo"); // bool(true) var_dump((bool) 2.3e5); // bool(true) var_dump((bool) array(12)); // bool(true) var_dump((bool) array()); // bool(false) var_dump((bool) "false"); // bool(true) Section 5.3: Float
$float = 0.123;
For historical reasons "double" is returned by gettype() in case of a float, and not simply "float"
Floats are floating point numbers, which allow more output precision than plain integers.
Floats and integers can be used together due to PHP's loose casting of variable types:
$sum = 3 + 0.14; echo $sum; // 3.14 php does not show float as float number like other languages, for example:
$var = 1; echo ((float) $var); //returns 1 not 1.0 Warning
Floating point precision
(From the PHP manual page)
Floating point numbers have limited precision. Although it depends on the system, PHP typically give a maximum relative error due to rounding in the order of 1.11e-16. Non elementary arithmetic operations may give larger errors, and error propagation must be considered when several operations are compounded.
Additionally, rational numbers that are exactly representable as floating point numbers in base 10, like 0.1 or 0.7, do not have an exact representation as floating point numbers in base 2 (binary), which is used internally, no matter the size of the mantissa. Hence, they cannot be converted into their internal binary counterparts without a small loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8, since the internal representation will be something like 7.9999999999999991118....
So never trust floating number results to the last digit, and do not compare floating point numbers directly for equality. If higher precision is necessary, the arbitrary precision math functions and gmp functions are available. Section 5.4: Strings
A string in PHP is a series of single-byte characters (i.e. there is no native Unicode support) that can be specified in four ways:
Single Quoted
Displays things almost completely "as is". Variables and most escape sequences will not be interpreted. The
Complete PHP Tips & Secrets for Professionals 30 exception is that to display a literal single quote, one can escape it with a back slash ', and to display a back slash, one can escape it with another backslash \
$my_string = 'Nothing is parsed, except an escap\'d apostrophe or backslash. $foo\n'; var_dump($my_string);
/* string(68) "Nothing is parsed, except an escap'd apostrophe or backslash. $foo\n" */ Double Quoted
Unlike a single-quoted string, simple variable names and escape sequences in the strings will be evaluated. Curly braces (as in the last example) can be used to isolate complex variable names.
$variable1 = "Testing!"; $variable2 = [ "Testing?", [ "Failure", "Success" ] ]; $my_string = "Variables and escape characters are parsed:\n\n"; $my_string .= "$variable1\n\n$variable2[0]\n\n"; $my_string .= "There are limits: $variable2[1][0]"; $my_string .= "But we can get around them by wrapping the whole variable in braces: {$variable2[1][1]}"; var_dump($my_string);
/* string(98) "Variables and escape characters are parsed:
Testing!
Testing?
There are limits: Array[0]"
But we can get around them by wrapping the whole variable in braces: Success
*/ Heredoc
In a heredoc string, variable names and escape sequences are parsed in a similar manner to double-quoted strings, though braces are not available for complex variable names. The start of the string is delimited by << $variable1 = "Including text blocks is easier"; $my_string = <<< EOF Everything is parsed in the same fashion as a double-quoted string, but there are advantages. $variable1; database queries and HTML output can benefit from this formatting. Once we hit a line containing nothing but the identifier, the string ends. EOF; var_dump($my_string); /* string(268) "Everything is parsed in the same fashion as a double-quoted string, but there are advantages. Including text blocks is easier; database queries and HTML output can benefit from this formatting. Once we hit a line containing nothing but the identifier, the string ends." */ Nowdoc Complete PHP Tips & Secrets for Professionals 31 A nowdoc string is like the single-quoted version of heredoc, although not even the most basic escape sequences are evaluated. The identifier at the beginning of the string is wrapped in single quotes. PHP 5.x Version≥5.3 $my_string = <<< 'EOF' A similar syntax to heredoc but, similar to single quoted strings, nothing is parsed (not even escaped apostrophes \' and backslashes \\.) EOF; var_dump($my_string); /* string(116) "A similar syntax to heredoc but, similar to single quoted strings, nothing is parsed (not even escaped apostrophes \' and backslashes \\.)" */ Section 5.5: Callable Callables are anything which can be called as a callback. Things that can be termed a "callback" are as follows: Anonymous functions Standard PHP functions (note: not language constructs) Static Classes non-static Classes (using an alternate syntax) Specific Object/Class Methods Objects themselves, as long as the object is found in key 0 of an array Example Of referencing an object as an array element: $obj = new MyClass(); call_user_func([$obj, 'myCallbackMethod']); Callbacks can be denoted by callable type hint as of PHP 5.4. $callable = function () { return 'value'; }; function call_something(callable $fn) { call_user_func($fn); } call_something($callable); Section 5.6: Resources A resource is a special type of variable that references an external resource, such as a file, socket, stream, document, or connection. $file = fopen('/etc/passwd', 'r'); Complete PHP Tips & Secrets for Professionals 32 echo gettype($file); # Out: resource echo $file; # Out: Resource id #2 There are different (sub-)types of resource. You can check the resource type using get_resource_type(): $file = fopen('/etc/passwd', 'r'); echo get_resource_type($file); #Out: stream $sock = fsockopen('www.google.com', 80); echo get_resource_type($sock); #Out: stream You can find a complete list of built-in resource types here. Section 5.7: Type Casting PHP will generally correctly guess the data type you intend to use from the context it's used in, however sometimes it is useful to manually force a type. This can be accomplished by prefixing the declaration with the name of the required type in parenthesis: $bool = true; var_dump($bool); // bool(true) $int = (int) true; var_dump($int); // int(1) $string = (string) true; var_dump($string); // string(1) "1" $string = (string) false; var_dump($string); // string(0) "" $float = (float) true; var_dump($float); // float(1) $array = ['x' => 'y']; var_dump((object) $array); // object(stdClass)#1 (1) { ["x"]=> string(1) "y" } $object = new stdClass(); $object->x = 'y'; var_dump((array) $object); // array(1) { ["x"]=> string(1) "y" } $string = "asdf"; var_dump((unset)$string); // NULL But be carefull: not all type casts work as one might expect: // below 3 statements hold for 32-bits systems (PHP_INT_MAX=2147483647) // an integer value bigger than PHP_INT_MAX is automatically converted to float: var_dump( 999888777666 ); // float(999888777666) // forcing to (int) gives overflow: var_dump((int) 999888777666 ); // int(-838602302) // but in a string it just returns PHP_INT_MAX var_dump((int) "999888777666"); // int(2147483647) var_dump((bool) []); // bool(false) (empty array) var_dump((bool) [false]); // bool(true) (non-empty array) Complete PHP Tips & Secrets for Professionals 33 Section 5.8: Type Juggling PHP is a weakly-typed language. It does not require explicit declaration of data types. The context in which the variable is used determines its data type; conversion is done automatically: $a = "2"; // string $a = $a + 2; // integer (4) $a = $a + 0.5; // float (4.5) $a = 1 + "2 oranges"; // integer (3) Section 5.9: Null PHP represents "no value" with the null keyword. It's somewhat similar to the null pointer in C-language and to the NULL value in SQL. Setting the variable to null: $nullvar = null; // directly function doSomething() {} // this function does not return anything $nullvar = doSomething(); // so the null is assigned to $nullvar Checking if the variable was set to null: if (is_null($nullvar)) { /* variable is null */ } if ($nullvar === null) { /* variable is null */ } Null vs undefined variable If the variable was not defined or was unset then any tests against the null will be successful but they will also generate a Notice: Undefined variable: nullvar: $nullvar = null; unset($nullvar); if ($nullvar === null) { /* true but also a Notice is printed */ } if (is_null($nullvar)) { /* true but also a Notice is printed */ } Therefore undefined values must be checked with isset: if (!isset($nullvar)) { /* variable is null or is not even defined */ } Section 5.10: Integers Integers in PHP can be natively specified in base 2 (binary), base 8 (octal), base 10 (decimal), or base 16 (hexadecimal.) $my_decimal = 42; $my_binary = 0b101010; $my_octal = 052; $my_hexadecimal = 0x2a; echo ($my_binary + $my_octal) / 2; // Output is always in decimal: 42 Integers are 32 or 64 bits long, depending on the platform. The constant PHP_INT_SIZE holds integer size in bytes. PHP_INT_MAX and (since PHP 7.0) PHP_INT_MIN are also available. printf("Integers are %d bits long" . PHP_EOL, PHP_INT_SIZE * 8); printf("They go up to %d" . PHP_EOL, PHP_INT_MAX); Complete PHP Tips & Secrets for Professionals 34 Integer values are automatically created as needed from floats, booleans, and strings. If an explicit typecast is needed, it can be done with the (int) or (integer) cast: $my_numeric_string = "123"; var_dump($my_numeric_string); // Output: string(3) "123" $my_integer = (int)$my_numeric_string; var_dump($my_integer); // Output: int(123) Integer overflow will be handled by conversion to a float: $too_big_integer = PHP_INT_MAX + 7; var_dump($too_big_integer); // Output: float(9.2233720368548E+18) There is no integer division operator in PHP, but it can be simulated using an implicit cast, which always 'rounds' by just discarding the float-part. As of PHP version 7, an integer division function was added. $not_an_integer = 25 / 4; var_dump($not_an_integer); // Output: float(6.25) var_dump((int) (25 / 4)); // (see note below) // Output: int(6) var_dump(intdiv(25 / 4)); // as of PHP7 // Output: int(6) (Note that the extra parentheses around (25 / 4) are needed because the (int) cast has higher precedence than the division) Chapter 6: Autoloading Primer require spl_autoload_require Section 6.1: Autoloading as part of a framework solution // autoload.php spl_autoload_register(function ($class) { require_once "$class.php"; }); // Animal.php class Animal { public function eats($food) { echo "Yum, $food!"; } } // Ruminant.php class Ruminant extends Animal { public function eats($food) { if ('grass' === $food) { parent::eats($food); } else { echo "Yuck, $food!"; } } } Complete PHP Tips & Secrets for Professionals 35 // Cow.php class Cow extends Ruminant { } // pasture.php require 'autoload.php'; $animal = new Cow; $animal->eats('grass'); Thanks to our generic autoloader, we have access to any class that follows our autoloader naming convention. In this example, our convention is simple: the desired class must have a file in the same directory named for the class and ending in ".php". Notice that the class name exactly matches the file name. Without autoloading, we would have to manually require base classes. If we built an entire zoo of animals, we'd have thousands of require statements that could more easily be replaced with a single autoloader. In the final analysis, PHP autoloading is a mechanism to help you write less mechanical code so you can focus on solving business problems. All you have to do is define a strategy that maps class name to file name. You can roll your own autoloading strategy, as done here. Or, you can use any of the standard ones the PHP community has adopted: PSR-0 or PSR-4. Or, you can use composer to generically define and manage these dependencies. Section 6.2: Inline class definition, no loading required // zoo.php class Animal { public function eats($food) { echo "Yum, $food!"; } } $animal = new Animal(); $animal->eats('meat'); PHP knows what Animal is before executing new Animal, because PHP reads source files top-to-bottom. But what if we wanted to create new Animals in many places, not just in the source file where it's defined? To do that, we need to load the class definition. Section 6.3: Manual class loading with require // Animal.php class Animal { public function eats($food) { echo "Yum, $food!"; } } // zoo.php require 'Animal.php'; $animal = new Animal; $animal->eats('slop'); // aquarium.php require 'Animal.php'; $animal = new Animal; $animal->eats('shrimp'); Here we have three files. One file ("Animal.php") defines the class. This file has no side effects besides defining the class and neatly keeps all the knowledge about an "Animal" in one place. It's easily version controlled. It's easily reused. Complete PHP Tips & Secrets for Professionals 36 Two files consume the "Animal.php" file by manually require-ing the file. Again, PHP reads source files top-to- bottom, so the require goes and finds the "Animal.php" file and makes the Animal class definition available before calling new Animal. Now imagine we had dozens or hundreds of cases where we wanted to perform new Animal. That would require (pun-intended) many, many require statements that are very tedious to code. Section 6.4: Autoloading replaces manual class definition loading // autoload.php spl_autoload_register(function ($class) { require_once "$class.php"; }); // Animal.php class Animal { public function eats($food) { echo "Yum, $food!"; } } // zoo.php require 'autoload.php'; $animal = new Animal; $animal->eats('slop'); // aquarium.php require 'autoload.php'; $animal = new Animal; $animal->eats('shrimp'); Compare this to the other examples. Notice how require "Animal.php" was replaced with require "autoload.php". We're still including an external file at run-time, but rather than including a specific class definition we're including logic that can include any class. It's a level of indirection that eases our development. Instead of writing one require for every class we need, we write one require for all classes. We can replace N require with 1 require. The magic happens with spl_autoload_register. This PHP function takes a closure and adds the closure to a queue of closures. When PHP encounters a class for which it has no definition, PHP hands the class name to each closure in the queue. If the class exists after calling a closure, PHP returns to its previous business. If the class fails to exist after trying the entire queue, PHP crashes with "Class 'Whatever' not found." Section 6.5: Autoloading with Composer Composer generates a vendor/autoload.php file. You might simply include this file and you will get autoloading for free. require __DIR__ . '/vendor/autoload.php'; This makes working with third-party dependencies very easy. You can also add your own code to the Autoloader by adding an autoload section to your composer.json. { "autoload": { "psr-4": {"YourApplicationNamespace\\": "src/"} } } Complete PHP Tips & Secrets for Professionals 37 In this section you define the autoload mappings. In this example its a PSR-4 mapping of a namespace to a directory: the /src directory resides in your projects root folder, on the same level as the /vendor directory is. An example filename would be src/Foo.php containing an YourApplicationNamespace\Foo class. Important: After adding new entries to the autoload section, you have to re-run the command dump-autoload to re-generate and update the vendor/autoload.php file with the new information. In addition to PSR-4 autoloading, Composer also supports PSR-0, classmap and files autoloading. See the autoload reference for more information. When you including the /vendor/autoload.php file it will return an instance of the Composer Autoloader. You might store the return value of the include call in a variable and add more namespaces. This can be useful for autoloading classes in a test suite, for example. $loader = require __DIR__ . '/vendor/autoload.php'; $loader->add('Application\\Test\\', __DIR__); Chapter 7: Exception Handling and Error Reporting Section 7.1: Setting error reporting and where to display them If it's not already done in php.ini, error reporting can be set dynamically and should be set to allow most errors to be shown: Syntax int error_reporting ([ int $level ] ) Examples // should always be used prior to 5.4 error_reporting(E_ALL); // -1 will show every possible error, even when new levels and constants are added // in future PHP versions. E_ALL does the same up to 5.4. error_reporting(-1); // without notices error_reporting(E_ALL & ~E_NOTICE); // only warnings and notices. // for the sake of example, one shouldn't report only those error_reporting(E_WARNING | E_NOTICE); errors will be logged by default by php, normally in a error.log file at the same level than the running script. in development environment, one can also show them on screen: ini_set('display_errors', 1); in production however, one should ini_set('display_errors', 0); and show a friendly problem message through the use of an Exception or Error handler. Section 7.2: Logging fatal errors Complete PHP Tips & Secrets for Professionals 38 In PHP, a fatal error is a kind of error that cannot be caught, that is, after experiencing a fatal error a program does not resume. However, to log this error or somehow handle the crash you can use register_shutdown_function to register shutdown handler. function fatalErrorHandler() { // Let's get last error that was fatal. $error = error_get_last(); // This is error-only handler for example purposes; no error means that // there were no error and shutdown was proper. Also ensure it will handle // only fatal errors. if (null === $error || E_ERROR != $error['type']) { return; } // Log last error to a log file. // let's naively assume that logs are in the folder inside the app folder. $logFile = fopen("./app/logs/error.log", "a+"); // Get useful info out of error. $type = $error["type"]; $file = $error["file"]; $line = $error["line"]; $message = $error["message"] fprintf( $logFile, "[%s] %s: %s in %s:%d\n", date("Y-m-d H:i:s"), $type, $message, $file, $line); fclose($logFile); } register_shutdown_function('fatalErrorHandler'); Reference: http://php.net/manual/en/function.register-shutdown-function.php http://php.net/manual/en/function.error-get-last.php http://php.net/manual/en/errorfunc.constants.php Chapter 8: Working with Dates and Time string date ( string $format [, int $timestamp = time() ] ) int strtotime ( string $time [, int $now ] ) Section 8.1: Getting the dierence between two dates / times The most feasible way is to use, the DateTime class. An example: // Calculate the diff $diff = $now->diff($twoYearsAgo); // $diff->y contains the difference in years between the two dates $yearsDiff = $diff->y; // $diff->m contains the difference in minutes between the two dates $monthsDiff = $diff->m; // $diff->d contains the difference in days between the two dates $daysDiff = $diff->d; // $diff->h contains the difference in hours between the two dates $hoursDiff = $diff->h; // $diff->i contains the difference in minutes between the two dates $minsDiff = $diff->i; // $diff->s contains the difference in seconds between the two dates $secondsDiff = $diff->s; // Total Days Diff, that is the number of days between the two dates $totalDaysDiff = $diff->days; // Dump the diff altogether just to get some details ;) var_dump($diff); Also, comparing two dates is much easier, just use the Comparison operators , like: Complete PHP Tips & Secrets for Professionals 39 $twoYearsAgo); // prints bool(true) var_dump($twoYearsAgo > $now); // prints bool(false) var_dump($twoYearsAgo <= $twoYearsAgo); // prints bool(true) var_dump($now == $now); // prints bool(true) Section 8.2: Convert a date into another format The Basics The simplist way to convert one date format into another is to use strtotime() with date(). strtotime() will convert the date into a Unix Timestamp. That Unix Timestamp can then be passed to date() to convert it to the new format. $timestamp = strtotime('2008-07-01T22:35:17.02'); $new_date_format = date('Y-m-d H:i:s', $timestamp); Or as a one-liner: $new_date_format = date('Y-m-d H:i:s', strtotime('2008-07-01T22:35:17.02')); Keep in mind that strtotime() requires the date to be in a valid format. Failure to provide a valid format will result in strtotime() returning false which will cause your date to be 1969-12-31. Using DateTime() As of PHP 5.2, PHP offered the DateTime() class which offers us more powerful tools for working with dates (and time). We can rewrite the above code using DateTime() as so: $date = new DateTime('2008-07-01T22:35:17.02'); $new_date_format = $date->format('Y-m-d H:i:s'); Working with Unix timestamps date() takes a Unix timestamp as its second parameter and returns a formatted date for you: $new_date_format = date('Y-m-d H:i:s', '1234567890'); DateTime() works with Unix timestamps by adding an @ before the timestamp: $date = new DateTime('@1234567890'); $new_date_format = $date->format('Y-m-d H:i:s'); If the timestamp you have is in milliseconds (it may end in 000 and/or the timestamp is thirteen characters long) you will need to convert it to seconds before you can can convert it to another format. There's two ways to do this: Trim the last three digits off using substr() Trimming the last three digits can be acheived several ways, but using substr() is the easiest: $timestamp = substr('1234567899000', -3); Divide the substr by 1000 You can also convert the timestamp into seconds by dividing by 1000. Because the timestamp is too large for 32 bit systems to do math on you will need to use the BCMath library to do the math as strings: Complete PHP Tips & Secrets for Professionals 40 $timestamp = bcdiv('1234567899000', '1000'); To get a Unix Timestamp you can use strtotime() which returns a Unix Timestamp: $timestamp = strtotime('1973-04-18'); With DateTime() you can use DateTime::getTimestamp() $date = new DateTime('2008-07-01T22:35:17.02'); $timestamp = $date->getTimestamp(); If you're running PHP 5.2 you can use the U formatting option instead: $date = new DateTime('2008-07-01T22:35:17.02'); $timestamp = $date->format('U'); Working with non-standard and ambiguous date formats Unfortunately not all dates that a developer has to work with are in a standard format. Fortunately PHP 5.3 provided us with a solution for that. DateTime::createFromFormat() allows us to tell PHP what format a date string is in so it can be successfully parsed into a DateTime object for further manipulation. $date = DateTime::createFromFormat('F-d-Y h:i A', 'April-18-1973 9:48 AM'); $new_date_format = $date->format('Y-m-d H:i:s'); In PHP 5.4 we gained the ability to do class member access on instantiation has been added which allows us to turn our DateTime() code into a one-liner: $new_date_format = (new DateTime('2008-07-01T22:35:17.02'))->format('Y-m-d H:i:s'); Unfortunately this does not work with DateTime::createFromFormat() yet. Section 8.3: Parse English date descriptions into a Date format Using the strtotime() function combined with date() you can parse different English text descriptions to dates: // Gets the current date echo date("m/d/Y", strtotime("now")), "\n"; // prints the current date echo date("m/d/Y", strtotime("10 September 2000")), "\n"; // prints September 10, 2000 in the m/d/Y format echo date("m/d/Y", strtotime("-1 day")), "\n"; // prints yesterday's date echo date("m/d/Y", strtotime("+1 week")), "\n"; // prints the result of the current date + a week echo date("m/d/Y", strtotime("+1 week 2 days 4 hours 2 seconds")), "\n"; // same as the last example but with extra days, hours, and seconds added to it echo date("m/d/Y", strtotime("next Thursday")), "\n"; // prints next Thursday's date echo date("m/d/Y", strtotime("last Monday")), "\n"; // prints last Monday's date echo date("m/d/Y", strtotime("First day of next month")), "\n"; // prints date of first day of next month echo date("m/d/Y", strtotime("Last day of next month")), "\n"; // prints date of last day of next month echo date("m/d/Y", strtotime("First day of last month")), "\n"; // prints date of first day of last month echo date("m/d/Y", strtotime("Last day of last month")), "\n"; // prints date of last day of last month Section 8.4: Using Predefined Constants for Date Format We can use Predefined Constants for Date format in date() instead of the conventional date format strings since PHP 5.1.0. Complete PHP Tips & Secrets for Professionals 41 Predefined Date Format Constants Available DATE_ATOM - Atom (2016-07-22T14:50:01+00:00) DATE_COOKIE - HTTP Cookies (Friday, 22-Jul-16 14:50:01 UTC) DATE_RSS - RSS (Fri, 22 Jul 2016 14:50:01 +0000) DATE_W3C - World Wide Web Consortium (2016-07-22T14:50:01+00:00) DATE_ISO8601 - ISO-8601 (2016-07-22T14:50:01+0000) DATE_RFC822 - RFC 822 (Fri, 22 Jul 16 14:50:01 +0000) DATE_RFC850 - RFC 850 (Friday, 22-Jul-16 14:50:01 UTC) DATE_RFC1036 - RFC 1036 (Fri, 22 Jul 16 14:50:01 +0000) DATE_RFC1123 - RFC 1123 (Fri, 22 Jul 2016 14:50:01 +0000) DATE_RFC2822 - RFC 2822 (Fri, 22 Jul 2016 14:50:01 +0000) DATE_RFC3339 - Same as DATE_ATOM (2016-07-22T14:50:01+00:00) Usage Examples echo date(DATE_RFC822); This will output: Fri, 22 Jul 16 14:50:01 +0000 echo date(DATE_ATOM,mktime(0,0,0,8,15,1947)); This will output: 1947-08-15T00:00:00+05:30 Chapter 9: Sending Email Parameter Details string $to The recipient email address string $subject The subject line string $message The body of the email string $additional_headers Optional: headers to add to the email Optional: arguments to pass to the configured mail send application in the string $additional_parameters command line Section 9.1: Sending Email - The basics, more details, and a full example A typical email has three main components: 1. A recipient (represented as an email address) 2. A subject 3. A message body Sending mail in PHP can be as simple as calling the built-in function mail(). mail() takes up to five parameters but the first three are all that is required to send an email (although the four parameters is commonly used as will be demonstrated below). The first three parameters are: 1. The recipient's email address (string) Complete PHP Tips & Secrets for Professionals 42 2. The email's subject (string) 3. The body of the email (string) (e.g. the content of the email) A minimal example would resemble the following code: mail('[email protected]', 'Email Subject', 'This is the email message body'); The simple example above works well in limited circumstances such as hardcoding an email alert for an internal system. However, it is common to place the data passed as the parameters for mail() in variables to make the code cleaner and easier to manage (for example, dynamically building an email from a form submission). Additionally, mail() accepts a fourth parameter which allows you to have additional mail headers sent with your email. These headers can allow you to set: the From name and email address the user will see the Reply-To email address the user's response will be sent to additional non-standards headers like X-Mailer which can tell the recipient this email was sent via PHP $to = '[email protected]'; // Could also be $to = $_POST['recipient']; $subject = 'Email Subject'; // Could also be $subject = $_POST['subject']; $message = 'This is the email message body'; // Could also be $message = $_POST['message']; $headers = implode("\r\n", [ 'From: John Conde The optional fifth parameter can be used to pass additional flags as command line options to the program configured to be used when sending mail, as defined by the sendmail_path configuration setting. For example, this can be used to set the envelope sender address when using sendmail/postfix with the -f sendmail option. $fifth = '[email protected]'; Although using mail() can be pretty reliable, it is by no means guaranteed that an email will be sent when mail() is called. To see if there is a potential error when sending your email, you should capture the return value from mail(). TRUE will be returned if the mail was successfully accepted for delivery. Otherwise, you will receive FALSE. $result = mail($to, $subject, $message, $headers, $fifth); NOTE: Although mail() may return TRUE, it does not mean the email was sent or that the email will be received by the recipient. It only indicates the mail was successfully handed over to your system's mail system successfully. If you wish to send an HTML email, there isn't a lot more work you need to do. You need to: 1. Add the MIME-Version header 2. Add the Content-Type header 3. Make sure your email content is HTML $to = '[email protected]'; $subject = 'Email Subject'; $message = '
Complete PHP Tips & Secrets for Professionals 43 Here's a full example of using PHP's mail() function
// Debugging tools. Only turn these on in your development environment. error_reporting(-1); ini_set('display_errors', 'On'); set_error_handler("var_dump");
// Special mail settings that can make mail less likely to be considered spam // and offers logging in case of technical difficulties. ini_set("mail.log", "/tmp/mail.log"); ini_set("mail.add_x_header", TRUE);
// The components of our email
$to = '[email protected]'; $subject = 'Email Subject'; $message = 'This is the email message body'; $headers = implode("\r\n", [ 'From: [email protected]', 'Reply-To: [email protected]', 'X-Mailer: PHP/' . PHP_VERSION ]);
// Send the email
$result = mail($to, $subject, $message, $headers);
// Check the results and react accordingly if ($result) {
// Success! Redirect to a thank you page. Use the // POST/REDIRECT/GET pattern to prevent form resubmissions // when a user refreshes the page.
header('Location: http://example.com/path/to/thank-you.php', true, 303); exit;
} else {
// Your mail was not sent. Check your logs to see if // the reason was reported there for you.
}
See Also
Official documentation
mail() PHP mail() configuration
Related Stack Overflow Questions
PHP mail form doesn't complete sending e-mail How do you make sure email you send programmatically is not automatically marked as spam?
Complete PHP Tips & Secrets for Professionals 44 How to use SMTP to send email Setting envelope from address
Alternative Mailers
PHPMailer SwiftMailer PEAR::Mail
Email Servers
Mercury Mail (Windows)
Related Topics
Post/Redirect/Get Section 9.2: Sending HTML Email Using mail()
This paragraph is bold.
This text is italic.